package com.gitee.l0km.codegen.decorator;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import com.gitee.l0km.codegen.base.generator.GeneratorConfiguration;
import com.gitee.l0km.com4j.base.ClassLoaderUtils;
import com.gitee.l0km.com4j.base.MiscellaneousUtils;
import com.gitee.l0km.javadocreader.JavadocReader;
import com.google.common.collect.Maps;

/**
 * enum support生成器参数对象
 * @author guyadong
 *
 */
public class EnumSupportConfiguration extends GeneratorConfiguration implements EnumSupportConstants{
	public static final String DECORATOR_FOLDER = "enumsupport";
	private List<Class<?>> baseClasses;
	private String sourcepath;
	private String classpath;
	private Map<Class<?>, List<String>> constantClasses;
	private boolean withAnnotation;
	public EnumSupportConfiguration() {
		super();
		// 指定模板文件夹
		this.defaultValue.setProperty(TEMPLATE_FOLDER_OPTION_LONG, DECORATOR_FOLDER);
		// 指定sourcepath的默认值，避免默认值为{@code null}
		this.defaultValue.setProperty(SOURCE_PREFIX_OPTION_LONG,"");
		// 指定classpath的默认值，避免默认值为{@code null}
		this.defaultValue.setProperty(CLASS_PATH_OPTION_LONG,"");
		this.defaultValue.setProperty(WITH_CONSTANT_OPTION_LONG,"");
		this.defaultValue.setProperty(WITH_ANNOT_OPTION_LONG,false);
	}
	
	/**
	 * 解析key指定的参数获取需要生成常量定义的类，
	 * 返回的Map对象KEY为需要生成常量的类，VALUE为继承的接口类(没有则为空表)
	 * @param key
	 */
	private Map<Class<?>, List<String>> getConstantClasses(String key){
		Map<Class<?>, List<String>> map = Maps.newLinkedHashMap();
		List<String> list = MiscellaneousUtils.elementsOf(getProperty(key),",;\t\n\r\f");
		for(String s:list) {
			int sep = s.indexOf(":");
			String clazzName;
			List<String> extendsClassNames;
			if(sep<0) {
				clazzName = s.trim();
				extendsClassNames = Collections.emptyList();
			}else {
				clazzName = s.substring(0, sep).trim();
				extendsClassNames = MiscellaneousUtils.elementsOf(s.substring(sep+1)," /");
			}
			Optional<Class<?>> found = baseClasses.stream()
					.filter(c->clazzName.equals(c.getName()) || clazzName.equals(c.getSimpleName()))
					.findFirst();
			if(found.isPresent()) {
				map.put(found.get(), extendsClassNames);
			}
		}
		return map;
	}
	@Override
	public void loadConfig(Options options, CommandLine cmd) throws ParseException {
		super.loadConfig(options, cmd);
		sourcepath = getProperty(SOURCE_PREFIX_OPTION_LONG);
		classpath = ClassLoaderUtils.normalizeClasspath((String)getProperty(CLASS_PATH_OPTION_LONG));
		JavadocReader.setSourcepath(sourcepath);
		JavadocReader.setClasspath(classpath);
		JavadocReader.resetRoot();
		baseClasses = getClasses(BASE_CLASS_OPTION_LONG, classpath, true);
		withAnnotation = getProperty(WITH_ANNOT_OPTION_LONG);
		constantClasses = getConstantClasses(WITH_CONSTANT_OPTION_LONG);
	}

	/**
	 * @return refClasses
	 */
	public List<Class<?>> getBaseClasses() {
		return baseClasses;
	}

	/**
	 * @return sourcepath
	 */
	public String getSourcepath() {
		return sourcepath;
	}

	/**
	 * @return classpath
	 */
	public String getClasspath() {
		return classpath;
	}

	/**
	 * @since 2.2.0
	 */
	public Map<Class<?>, List<String>> getConstantClasses() {
		return constantClasses;
	}

	public boolean isWithAnnotation() {
		return withAnnotation;
	}
}
